;
;    SOUND BLASTER
;
;    Compile with FASM for Menuet
;
   
use32
   
    org     0x0
   
    db      'MENUET01'              ; 8 byte id
    dd      0x01
    dd      START                   ; program start
    dd      I_END                   ; program image size
    dd      0x80000                 ; required amount of memory
    dd      0xfff0                  ; stack position
    dd      0,0
  
vol_data             dd 0x40000
playposition         dd 0x20000
next_tic             dd 0x0
onoff                dd 0x0
pause_between_songs  dd 100
delay                dd 100
repeat_song          db 0
mono_stereo          dd 1

pry  equ 10
ypos equ -10


; 0x10000 data from hd
; 0x20000 play position for sb
; 0x40000 volume indicator data
   
   
START:                          ; start of execution
   
    call draw_window            ; at first, draw the window
   
    mov  eax,26
    mov  ebx,9
    int  0x40
    mov  [next_tic],eax
   
still:
   
    mov  [delay],145
    cmp  [mono_stereo],2
    jne  no_stereo
    mov  [delay],73
  no_stereo:
   
    mov  eax,55
    mov  ebx,2
    mov  ecx,0
    mov  edx,[mono_stereo]
    int  0x40
   
    mov  eax,23                 ; wait here for event
    mov  ebx,1
    int  0x40
   
    cmp  eax,0
    jne  do_task
   
still2:
   
    cmp  [onoff],0
    je   still
   
    mov  eax,26
    mov  ebx,9
    int  0x40
    mov  ebx,[next_tic]
    cmp  eax,ebx
    jge  play_wave_block
   
    mov  edi,[next_tic]
    sub  edi,eax
    mov  eax,[delay]
    sub  eax,edi
    mov  edi,eax
    call draw_volume
   
    jmp  still
   
  do_task:
   
    cmp  eax,1                  ; redraw request ?
    je   red
    cmp  eax,2                  ; key in buffer ?
    je   key
    cmp  eax,3                  ; button in buffer ?
    je   button
   
    cmp  eax,16+4
    jne  no_irman
    mov  eax,42
    mov  ebx,4
    int  0x40
    dec  [ir_count]
    cmp  bl,140
    jne  no_first
    mov  [ir_count],3
  no_first:
    cmp  [ir_count],0
    jne  no_irman
    call give_wav
    cmp  bl,215
    je   play
    mov  ah,4
;;    cmp  bl,55
;;    je   rev
    mov  ah,3
;;;    cmp  bl,183
;;;    je   rev
    cmp  bl,127
    jne  no_block_dec
    add  [block],65536/512*10
  no_block_dec:
    cmp  bl,191
    jne  no_block_inc
    sub  [block],65536/512*10
  no_block_inc:
    jmp  still
   no_irman:
   
    jmp  still
   
  play_wave_block:
   
    mov  eax,55    ; load wave
    mov  ebx,0
    mov  ecx,[playposition]
    int  0x40
   
    mov  eax,55    ; play wave
    mov  ebx,1
    int  0x40
   
    mov  eax,26
    mov  ebx,9
    int  0x40
    add  eax,[delay]
    mov  [next_tic],eax
   
    call draw_wave
    call read_wav
   
    jmp  still
   
  red:                          ; redraw
    call draw_window
    jmp  still
   
  key:                          ; key
    mov  eax,2                  ; just read it and ignore
    int  0x40
    jmp  still2
   
  button:                       ; button
    mov  eax,17                 ; get id
    int  0x40

    mov  ebx , eax
    shr  ebx , 8
    cmp  ebx , 0x106
    jne  noclose3
    mov  eax , -1
    int  0x40
  noclose3:

    cmp  ah,6
    jne  no_ir
    call enable_ir
    jmp  still
  no_ir:
   
    cmp  ah,7
    jne  no_file_name
    call read_string
    jmp  still
  no_file_name:
   
    cmp  ah,2                   ; button id=2
    jne  noplay
  play:
    mov  eax,[onoff]
    not  eax
    and  eax,1
    mov  [onoff],eax
    mov  [playposition],0x20000
    mov  [block],2
    call read_header
    call read_wav
;    mov  [next_tic],0
    jmp  still
   
  noplay:
   
    cmp  ah,3
    jb   no_rev
    cmp  ah,4
    jg   no_rev
    sub  ah,3
    shr  eax,8
    imul eax,4000
    sub  eax,2000
    add  [block],eax
    cmp  [block],0x0f000000
    jb   block_ok
    mov  [block],2
  block_ok:
    call display_progress
    jmp  still2
  no_rev:
   
    cmp  ah,5                   ; repeat song ?
    jne  no_repeat
    mov  al,[repeat_song]
    inc  al
    and  eax,1
    mov  [repeat_song],al
    shl  eax,2
    mov  eax,[repeat_text+eax]
    mov  [text+40*5+31],eax
    call draw_window
    jmp  still
    repeat_text: db 'OFF ON  '
  no_repeat:
   
   
    cmp  ah,1
    jne  noclose
    cmp  [infrared_enabled],1
    jne  no_dis
    mov  eax,45
    mov  ebx,1
    mov  ecx,4
    int  0x40
    mov  eax,46
    mov  ebx,1
    mov  ecx,0x3f0
    mov  edx,0x3ff
    int  0x40
  no_dis:
    mov  eax,-1                 ; close this program
    int  0x40
  noclose:

            
    jmp  still2
   
   
give_wav:
   
    pusha
   
    mov  eax,55
    mov  ebx,0
    mov  ecx,0x20000
    int  0x40
   
    popa
    ret
   
ir_count db 0x0
   
   
drop_rate dd 100
   
draw_volume:
   
; edi = tic to show
   
    ret
   
    pusha
   
    add  edi,[vol_data]
   
    mov  eax,[drop_rate]
    cmp  eax,2
    jb   no_drop
    sub  eax,2
  no_drop:
    mov  [drop_rate],eax
   
    movzx eax,byte [edi]
    cmp  eax,[drop_rate]
    jge  drop_ok
    mov  eax,[drop_rate]
    mov  [edi],al
    jmp  fixed_drop
  drop_ok:
    mov  [drop_rate],eax
  fixed_drop:
   
    mov  eax,13
    mov  ebx,320*65536+20
    mov  ecx,50*65536+1
    movzx edx,byte [edi]
    shr   edx,1
    mov  esi,128
    sub  esi,edx
    add  ecx,esi
    mov  edx,0x00ff00
    int  0x40
   
    mov  eax,13
    mov  ebx,320*65536+20
    movzx edx,byte [edi]
    shr  edx,1
    mov  ecx,edx
    add  ecx,(50+128)*65536+1
    shl  edx,16
    sub  ecx,edx
    mov  edx,0xff0000
    int  0x40
   
    popa
   
    ret
   
   
read_header:
   
    pusha
   
    mov  dword [file_info+4],0               ; block to read
    mov  dword [file_info+8],1               ; blocks to read
    mov  dword [file_info+12],0x10000+1024   ; return data pointer
    mov  dword [file_info+16],0x60000        ; work area for os
   
    mov  eax,58
    mov  ebx,file_info
    int  0x40
   
    movzx eax,byte [0x10000+1024+12+10]
    mov   [channels],eax
    movzx eax,byte [0x10000+1024+12+20]
    mov   [bytes_per_sample],eax
   
    cmp   [0x10000+1024],dword 'RIFF'
    jne   unknownformat
    cmp   [0x10000+1024+8],dword 'WAVE'
    jne   unknownformat
   
    mov [addb],128
    cmp [channels],1
    je  addb_ok
    mov [addb],256
  addb_ok:
    cmp [bytes_per_sample],1
    je  addb_ok2
    mov [addb],256
  addb_ok2:
   
    mov [bmul],256
    cmp [addb],256
    je  bmok
    mov [bmul],512
  bmok:
   
    cmp [bytes_per_sample],4
    jne no16s
    mov [addb],512   ;mono_stereo
    mov ecx,[mono_stereo]
    shr ecx,1
    shr [addb],cl
    mov [bmul],128   ;mono_stereo
    shl [bmul],cl
  no16s:
   
    popa
   
    ret
   
unknownformat:
   
    mov  [onoff],0
   
    call display_progress
   
    mov  eax,13
    mov  ebx,190*65536+10
    mov  ecx,104*65536+10
    mov  edx,0xff0000
    int  0x40
    pusha
   
    mov  eax,5
    mov  ebx,[pause_between_songs]
    int  0x40
   
    popa
    mov  eax,13
    mov  edx,0x000000
    int  0x40
   
    popa
   
    ret
   
   
   
channels           dd 0x0  ; 1=mono, 2 stereo
bytes_per_sample   dd 0x0  ; 1=8 2=2*8/16 4=16
   
buffer dd 0x20000
   
block  dd 0x2
addb   dd 256    ;  128 = mono 8 bit , 256 = stereo 8 bit/16 bit mono
bmul   dd 0x0    ;  512 = mono 8 bit , 256 = stereo 8 bit/16 bit mono
   
file_size dd 100
   
current_play dd wavfile+40*0
   
   
read_wav:
   
    pusha
   
  new_file:
   
    mov  edx,[block]
   
  newread:
   
    mov  dword [file_info+4],edx             ; block to read
    mov  dword [file_info+8],1               ; blocks to read
    mov  dword [file_info+12],0x10000+1024   ; return data pointer
    mov  dword [file_info+16],0x60000        ; work area for os
   
    mov  eax,58
    mov  ebx,file_info
    int  0x40
   
   
    pusha
    mov  eax,11
    int  0x40
    cmp  eax,1
    jne  no_wd
    call draw_window
  no_wd:
    popa
   
    pusha
    mov  eax,38
    mov  ebx,1*65536+128
    mov  ecx,71*65536+71
    add  ebx,25*65536+25
    mov  edx,0x555555
;    int  0x40
    mov  eax,38
    mov  ebx,[esp+32-12]
    and  ebx,65536/512 -1
    or   ebx,1*65536
    add  ebx,25*65536+25
    mov  ecx,71*65536+71
    mov  edx,0x999999
;    int  0x40
    popa
   
    cmp  eax,0
    je   conp
   
    movzx eax,byte [repeat_song]
    inc   eax
    and   eax,1
    imul  eax,40
    mov  [current_play],wavfile
  play_ok:
   
    mov  [onoff],1
    mov  [playposition],0x20000
    mov  [block],20
   
    mov  eax,5
    mov  ebx,[pause_between_songs]
    add  ebx,[delay]
    int  0x40
   
    call read_header
   
    cmp  [onoff],0
    je   noplay2
    cmp  [repeat_song],0
    je   noplay2
   
    call display_progress
   
    jmp  new_file
   
  noplay2:
   
    mov  [onoff],0
    mov  [block],2
    call display_progress
   
    popa
    ret
  conp:
   
    mov  [file_size],ebx
   
    mov  esi,0x10000+1024   ; 8 bit stereo & 16 bit mono
    mov  edi,edx
    sub  edi,[block]
    imul edi,[bmul]
    add  edi,[buffer]
    mov  ecx,512
   
  movedata:
   
    mov  al,[esi+1]
   
    cmp  [bytes_per_sample],4 ; for 16 bit stereo
    jne  no_16_stereo
    mov  al,[esi+1]
    add  al,128
  no_16_stereo:
   
    cmp  [bytes_per_sample],1 ; for 16 bit mono
    je   no_16_mono
    cmp  [channels],2
    je   no_16_mono
    mov  al,[esi+1]
    add  al,128
  no_16_mono:
   
    mov  [edi],al
    mov  eax,[bytes_per_sample]
    cmp  [mono_stereo],1
    je   bps1
    mov  eax,[bytes_per_sample]
    push ecx
    mov  ecx,[mono_stereo]
    dec  ecx
    shr  eax,cl
    pop  ecx
  bps1:
    add  esi,eax ; 2;[bytes_per_sample] ; / mono_stereo
    add  edi,1
    loop movedata
   
    add  edx,1
    mov  ecx,[block]
    add  ecx,[addb]
    cmp  edx,ecx
    jbe  newread
   
    mov  ecx,[addb]
    add  [block],ecx
   
    call display_progress
   
  rewr:
   
    popa
   
    call set_vol_data
   
    ret
   
   
set_vol_data:
   
;    ret
   
    pusha
   
    mov  eax,65536
    xor  edx,edx
    mov  ebx,[delay]
    div  ebx
    push eax
   
    mov  esi,[playposition]
    mov  edi,[vol_data]
    mov  ecx,[delay]
   
  svd:
   
    mov   eax,0
    mov   edx,100
  svd3:
    movzx ebx,byte [esi]
    cmp   ebx,128
    jge   svd2
    mov   ebx,0
   svd2:
    sub   ebx,128
    shl   ebx,1
   
    cmp   ebx,ebp
    jbe   svd4
    mov   edx,ebx
   svd4:
   
    inc   esi
    inc   eax
    cmp   eax,[esp]
    jb    svd3
   
    mov  [edi],dl
    inc  edi
    loop svd
   
    pop  eax
    popa
   
    ret
   
   
addr  dd   0x0
ya    dd   0x0
   
   
read_string:
   
     mov  [onoff],0
   
    mov  [addr],wavfile
    mov  [ya],30
   
    mov  edi,[addr]
    mov  al,'_'
    mov  ecx,32
    rep  stosb
   
    call print_text
   
    mov  edi,[addr]
   
  f11:
    mov  eax,10
    int  0x40
    cmp  eax,2
    jne  read_done
    mov  eax,2
    int  0x40
    shr  eax,8
    cmp  eax,13
    je   read_done
    cmp  eax,8
    jnz  nobsl
    cmp  edi,[addr]
    jz   f11
    sub  edi,1
    mov  [edi],byte '_'
    call print_text
    jmp  f11
  nobsl:
    cmp  eax,dword 31
    jbe  f11
    cmp  eax,dword 95
    jb   keyok
    sub  eax,32
  keyok:
    mov  [edi],al
   
    call print_text
   
    add  edi,1
    mov  esi,[addr]
    add  esi,32
    cmp  esi,edi
    jnz  f11
   
  read_done:
   
    mov  ecx,[addr]
    add  ecx,38
    sub  ecx,edi
    mov  eax,0
    cld
    rep  stosb
   
    call print_text
   
    ret
   
   
print_text:
   
display_progress:
   
    pusha

    mov  eax,13                ; gray progress bar
    mov  ebx,25*65536+215
    mov  ecx,(61-pry)*65536+8
    mov  edx,[border]
    int  0x40
   
    cmp  [onoff],1
    je   yes_playing
    mov  [block],0
    mov  [file_size],100*512
  yes_playing:
    mov  eax,[block]           ; yellow progress bar
    imul eax,214
    xor  edx,edx
    mov  ebx,[file_size]
    shr  ebx,9
    or   ebx,1
    div  ebx
    mov  ebx,eax
    and  ebx,0xff
    mov  eax,13
    add  ebx,25*65536
    mov  ecx,(61-pry)*65536+1
    mov  edx,[drawp]
   newbar:
    int  0x40
    add  edx,0x101010
    add  ecx,1*65536
    cmp  ecx,(65-pry)*65536
    jb   newbar
   newbar2:
    int  0x40
    sub  edx,0x101010
    add  ecx,1*65536
    cmp  ecx,(69-pry)*65536
    jb   newbar2
   
   
    mov  esi,[current_play]
    mov  edi,now_playing
    mov  ecx,40
    cld
    rep  movsb
   
    mov  eax,13
    mov  ebx,42*65536+33*6
    mov  ecx,(114+ypos)*65536+11
    mov  edx,[bgr]
    int  0x40
   
    mov  eax,4
    mov  ebx,42*65536+117+ypos
    mov  ecx,0x000000
    mov  edx,now_playing
    mov  esi,38
    int  0x40
   
    popa
   
    ret
   
   
shape_window:
   
    ret
   
    pusha
   
    mov  eax,50
    mov  ebx,0
    mov  ecx,shape_reference
    int  0x40
   
    mov  eax,50
    mov  ebx,1
    mov  ecx,4
    int  0x40
   
    popa
   
    ret
   
   
shape_reference:
   
times 1  db  1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0
times 9  db  1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
   
infrared_enabled db 0x0
   
   
enable_ir:
   
    pusha
   
    mov  eax,46
    mov  ebx,0
    mov  ecx,0x3f0
    mov  edx,0x3ff
    int  0x40
   
    mov  eax,45
    mov  ebx,0
    mov  ecx,4
    int  0x40
   
    mov  eax,40
    mov  ebx,10000b shl 16 + 111b
    int  0x40
   
    mov  [infrared_enabled],1
   
    popa
   
    ret
   
   
   
;   *********************************************
;   *******  WINDOW DEFINITIONS AND DRAW ********
;   *********************************************

   
   
draw_window:
   
    pusha
   
    inc  [next_tic]
   
    mov  eax,12                    ; function 12:tell os about windowdraw
    mov  ebx,1                     ; 1, start of draw
    int  0x40
                                   ; DRAW WINDOW
    mov  eax,0                     ; function 0 : define and draw window
    mov  ebx,100*65536+265         ; [x start] *65536 + [x size]
    mov  ecx,100*65536+142+ypos         ; [y start] *65536 + [y size]
    mov  edx,[bgr]
    add  edx,0x04000000            ; color of work area RRGGBB,8->color gl
    mov  esi,window_label
    mov  edi,menu_struct 
    int  0x40
   
    mov  eax,8                     ; START/STOP  - id 2
    mov  ebx,24*65536+77
    mov  ecx,(80+ypos)*65536+16
    mov  edx,2
    mov  esi,[border]
    add  esi,0x10000000
    mov  edi,0
    int  0x40
   
    inc  edx                       ; << / >>     - id 3 , 4
    add  ebx,86*65536-57
    mov  eax,8
    mov  edi,0
    int  0x40
    inc  edx
    add  ebx,24*65536
    mov  eax,8
    mov  edi,0
    int  0x40
   
    mov  eax,8                      ; REPEAT
    add  ebx,29*65536+56
    inc  edx
    mov  edi,0
    int  0x40
   
    mov  eax,8                      ; enable infrared
    add  ebx,98*65536-35
    add  ecx,10*65536+10
    inc  edx
;    int  0x40
   
    pusha
    mov  eax,8
    mov  ebx,25*65536+9
    mov  ecx,(115+ypos)*65536+9
    inc  edx
    mov  edi,0
    int  0x40
    popa
   
    mov  eax,4
    shr  ecx,16
    mov  bx,cx
    add  ebx,2*65536+4
    mov  ecx,0xffffff
    mov  edx,infrared_text
    mov  esi,10
;    int  0x40
    add  ebx,11
    add  edx,10
    mov  eax,4
;    int  0x40
   
    mov  ebx,25*65536+35+ypos           ; draw info text with function 4
    mov  ecx,0x000000
    mov  edx,text
    mov  esi,40
  newline:
    mov  eax,4
    int  0x40
    add  ebx,10
    add  edx,40
    cmp  [edx],byte 'x'
    jne  newline
   
    call display_progress
   
    call draw_wave
   
    mov  eax,12
    mov  ebx,2
    int  0x40
   
    popa
    ret
   
   
   
   
draw_wave:
   
    ret
   
    pusha
   
    mov   eax,13
    mov   ebx,260*65536+43
    mov   ecx,42*65536+32
    mov   edx,[border]
    int   0x40
   
    mov   esi,[playposition]
    mov   ebx,260
   npix:
    mov   eax,1
    inc   ebx
    movzx ecx,byte [esi]
    shr   ecx,3
    add   ecx,42
    mov   edx,[drawc];0x2255aa
    int   0x40
   
    add   esi,2
   
    cmp   ebx,300
    jbe   npix
   
    popa
   
    ret
   
   
; DATA AREA

menu_struct:

    dq   0                 ; Version

    dq   0x100             ; Start value of ID to return ( ID + Line )

                           ; Returned when menu closes and
                           ; user made no selections.

    db   0,'FILE',0        ; ID = 0x100 + 1
    db   1,'New',0         ; ID = 0x100 + 2
    db   1,'Open..',0      ; ID = 0x100 + 3
    db   1,'Save..',0      ; ID = 0x100 + 4
    db   1,'-',0           ; ID = 0x100 + 5
    db   1,'Quit',0        ; ID = 0x100 + 6

    db   0,'HELP',0        ; ID = 0x100 + 7
    db   1,'Contents..',0  ; ID = 0x100 + 8
    db   1,'About..',0     ; ID = 0x100 + 9

    db   255
   
infrared_text: db  'IRMAN     INFRAR      '
   
   
textc   dd  0xffffff
bgr     dd  0xf0f0f0
drawc   dd  0x2255aa
drawp   dd  0x404070
border  dd  0xc0c0c0
   
text:
 ;   db 'Define SB, HD and partition in setup.   '
    db '                                        '
    db '                                        '
    db '                                        '
    db '                                        '
    db '                                        '
    db ' START/STOP    <<  >>   REPEAT:OFF      '
    db 'x <- END MARKER, DONT DELETE            '
now_playing:
    db '                                        '
    db 'xx                                      '
   
file_info:
   
    dd  0   ; read
    dd  0
    dd  0
    dd  0
    dd  0
   
wavfile:
    db '/HD/1/FILE.WAV',0                
    db '                                        '
    db '                                        '
   

window_label:

     db   ' WAVE PLAYER',0
   
I_END:
   
   
   
   
   
